package com.asr.testclient.service;

import com.asr.testclient.model.ClientMessage;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.net.URI;

/**
 * ASR WebSocket客户端
 * 负责与ASR服务器建立WebSocket连接并进行通信
 */
public class ASRWebSocketClient extends WebSocketClient {
    private static final Logger logger = LoggerFactory.getLogger(ASRWebSocketClient.class);
    private final Object controller;

    /**
     * 构造函数
     * @param serverUri WebSocket服务器URI
     * @param controller 主控制器实例，用于回调
     */
    public ASRWebSocketClient(URI serverUri, Object controller) {
        super(serverUri);
        this.controller = controller;
        logger.info("Created WebSocket client for URI: {}", serverUri);
    }

    /**
     * 连接建立时的回调
     * @param handshake 握手信息
     */
    @Override
    public void onOpen(ServerHandshake handshake) {
        logger.info("WebSocket connection established. Status: {}", handshake.getHttpStatus());
        
        // 发送模式选择消息（选择实时模式）
        try {
            String modeSelectMessage = "{\"type\":\"select_mode\",\"mode\":\"realtime\"}";
            send(modeSelectMessage);
            logger.info("Sent mode selection message: realtime mode");
        } catch (Exception e) {
            logger.error("Failed to send mode selection message", e);
        }
        
        // 在EDT线程中调用控制器回调
        SwingUtilities.invokeLater(() -> {
            try {
                controller.getClass()
                    .getMethod("onConnectionEstablished")
                    .invoke(controller);
            } catch (Exception e) {
                logger.error("Failed to invoke onConnectionEstablished callback", e);
            }
        });
    }

    /**
     * 接收到消息时的回调
     * @param message 接收到的消息内容
     */
    @Override
    public void onMessage(String message) {
        logger.debug("Received message: {}", message);
        
        // 在EDT线程中调用控制器回调
        SwingUtilities.invokeLater(() -> {
            try {
                controller.getClass()
                    .getMethod("onMessageReceived", String.class)
                    .invoke(controller, message);
            } catch (Exception e) {
                logger.error("Failed to invoke onMessageReceived callback", e);
            }
        });
    }

    /**
     * 连接关闭时的回调
     * @param code 关闭代码
     * @param reason 关闭原因
     * @param remote 是否由远程端关闭
     */
    @Override
    public void onClose(int code, String reason, boolean remote) {
        String closeSource = remote ? "remote" : "local";
        logger.info("WebSocket connection closed by {}. Code: {}, Reason: {}", 
                   closeSource, code, reason);
        
        // 在EDT线程中调用控制器回调
        SwingUtilities.invokeLater(() -> {
            try {
                controller.getClass()
                    .getMethod("onConnectionClosed")
                    .invoke(controller);
            } catch (Exception e) {
                logger.error("Failed to invoke onConnectionClosed callback", e);
            }
        });
    }

    /**
     * 发生错误时的回调
     * @param ex 异常对象
     */
    @Override
    public void onError(Exception ex) {
        logger.error("WebSocket error occurred: {}", ex.getClass().getName(), ex);
        
        // 提供更详细的错误信息
        String errorMessage;
        if (ex.getMessage() != null && !ex.getMessage().isEmpty()) {
            errorMessage = ex.getMessage();
        } else {
            errorMessage = ex.getClass().getSimpleName() + ": 未知错误";
        }
        
        // 根据异常类型提供更友好的错误消息
        if (ex instanceof java.net.ConnectException) {
            errorMessage = "连接被拒绝，请检查服务器是否运行";
        } else if (ex instanceof java.net.UnknownHostException) {
            errorMessage = "无法解析服务器地址: " + ex.getMessage();
        } else if (ex instanceof java.net.SocketTimeoutException) {
            errorMessage = "连接超时，请检查网络连接";
        } else if (ex instanceof java.io.IOException) {
            errorMessage = "网络IO错误: " + ex.getMessage();
        }
        
        final String finalErrorMessage = errorMessage;
        
        // 在EDT线程中调用控制器回调
        SwingUtilities.invokeLater(() -> {
            try {
                controller.getClass()
                    .getMethod("onConnectionFailed", String.class)
                    .invoke(controller, finalErrorMessage);
            } catch (Exception e) {
                logger.error("Failed to invoke onConnectionFailed callback", e);
            }
        });
    }

    /**
     * 发送音频片段消息（实时识别模式）
     * @param base64Data Base64编码的音频数据
     * @throws IllegalStateException 如果WebSocket连接未打开
     * @throws IllegalArgumentException 如果base64Data为空
     */
    public void sendAudioChunk(String base64Data) {
        if (!isOpen()) {
            logger.error("Cannot send audio chunk: WebSocket connection is not open");
            throw new IllegalStateException("WebSocket连接未打开");
        }

        if (base64Data == null || base64Data.trim().isEmpty()) {
            logger.error("Cannot send empty base64 data");
            throw new IllegalArgumentException("Base64数据不能为空");
        }

        try {
            // 构建audio_chunk消息
            String json = String.format("{\"type\":\"audio_chunk\",\"audio\":\"%s\"}", base64Data);
            
            if (json == null || json.isEmpty()) {
                logger.error("Failed to create JSON message");
                throw new IllegalStateException("消息创建失败");
            }
            
            logger.info("Sending audio chunk. Data length: {}", base64Data.length());
            logger.debug("JSON message length: {} bytes", json.length());
            
            send(json);
            logger.info("Audio chunk sent successfully");
            
        } catch (IllegalStateException | IllegalArgumentException e) {
            // 重新抛出已知的异常
            throw e;
        } catch (Exception e) {
            logger.error("Unexpected error sending audio chunk", e);
            throw new RuntimeException("发送消息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 发送结束音频消息
     * @throws IllegalStateException 如果WebSocket连接未打开
     */
    public void sendEndAudio() {
        if (!isOpen()) {
            logger.error("Cannot send end audio: WebSocket connection is not open");
            throw new IllegalStateException("WebSocket连接未打开");
        }

        try {
            String json = "{\"type\":\"end_audio\"}";
            send(json);
            logger.info("End audio message sent successfully");
        } catch (Exception e) {
            logger.error("Unexpected error sending end audio message", e);
            throw new RuntimeException("发送结束消息失败: " + e.getMessage(), e);
        }
    }
}
